﻿using DatabaseTransfer.Connections;
using DatabaseTransfer.Factories;
using DatabaseTransfer.Interfaces;
using DatabaseTransfer.Logs;
using DatabaseTransfer.Tables;
using DatabaseTransfer.Transfer;
using DatabaseTransfer.Utils;
using log4net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DatabaseTransfer.Forms
{
    public partial class ColumnMatcher : Form
    {
        private static ILog logger = LogFactory.GetLogger(typeof(ColumnMatcher));
        private Table srcTable;
        private Table destTable;
        private AbstractDatabase srcDatabase;
        private AbstractDatabase destDatabase;

        public ColumnMatcher(Table srcTable, Table destTable)
        {
            // TODO: Complete member initialization
            this.srcTable = srcTable;
            this.destTable = destTable;
            this.srcDatabase = srcTable.Database;
            this.destDatabase = destTable.Database;
            InitializeComponent();
        }
        public ColumnMatcher(DatabaseTransferSerializer dts)
        {
            this.srcTable = dts.SourceTable;
            this.destTable = dts.DestinationTable;
            this.srcDatabase = DatabaseFactory.GetDatabase(dts.SourceConnector);
            this.destDatabase = DatabaseFactory.GetDatabase(dts.DestinationConnector);
            InitializeComponent();
            SetupColumns();
            linkageBox.DataSource = dts.LinkageList;
        }

        public void SetupColumns()
        {
            SetupSourceColumns();
            SetupDestinationColumns();
        }

        private void SetupSourceColumns()
        {
            new Thread(new ThreadStart(() =>
            {
                List<TableColumn> srcCols = this.srcDatabase.GetTableColumns(this.srcTable.TableName);
                if (srcCols == null) return;
                srcTable.TableColumns = srcCols;
                if (this.srcColumns.InvokeRequired)
                {
                    this.Invoke((MethodInvoker)delegate { this.srcColumns.DataSource = srcCols; });
                }
                else
                {
                    this.srcColumns.DataSource = srcCols;
                }
            })).Start();

            destColumns.ContextMenuStrip = staticStrip;
        }

        private void SetupDestinationColumns()
        {
            new Thread(new ThreadStart(() =>
            {
                List<TableColumn> destCols = this.destDatabase.GetTableColumns(this.destTable.TableName);
                if (destCols == null) return;
                destTable.TableColumns = destCols;
                if (this.destColumns.InvokeRequired)
                {
                    this.Invoke((MethodInvoker)delegate { this.destColumns.DataSource = destCols; });
                }
                else
                {
                    this.destColumns.DataSource = destCols;
                }
            })).Start();
        }

        private void linkColumsBtn_Click(object sender, EventArgs e)
        {
            TableColumn srcColumn = (TableColumn)srcColumns.SelectedItem;
            TableColumn destColumn = (TableColumn)destColumns.SelectedItem;

            if (srcColumn  == null)
            {
                MessageBox.Show("Source column wasn't selected");
                logger.Warn("No source column selected");
                return;
            }

            if (destColumn == null)
            {
                MessageBox.Show("Destination column wasn't selected");
                logger.Warn("No detination column selected");
                return;
            }

            ColumnLinkage cl = new ColumnLinkage(srcColumn, destColumn);
            BindingSource bs = (BindingSource) linkageBox.DataSource;
            
            if (srcColumn.ColumnType != destColumn.ColumnType)
            {
                DialogResult result = MessageBox.Show("Source Column Type is not the same as Destination. Add conversion text?", "", MessageBoxButtons.YesNo);
                if (result != DialogResult.Yes) return;

                UserInput input = new UserInput("Please Enter Conversion Format");
                input.OnOkButtonClick += (obj, evt) =>
                {
                    cl.Conversion = input.InputValue;
                };
                input.ShowDialog();
                bs.Add(cl);
            }
            else
            {
                bs.Add(cl);
            }

        }

        private void staticValueToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UserInput input = new UserInput("Please Enter Static Value");
            input.OnOkButtonClick += (obj, evt) =>
            {
                TableColumn destColumn = (TableColumn)destColumns.SelectedItem;
                ColumnLinkage cl = new ColumnLinkage(destColumn, input.InputValue);
                ((BindingSource)linkageBox.DataSource).Add(cl);
            };
            input.ShowDialog();
        }

        private void xferButton_Click(object sender, EventArgs e)
        {
            BindingSource bs = (BindingSource)linkageBox.DataSource;

            List<ColumnLinkage> linkages = new List<ColumnLinkage>();

            ColumnLinkage[] linkagesArr = new ColumnLinkage[bs.Count];

            bs.CopyTo(linkagesArr, 0);

            linkages.AddRange(linkagesArr);

            DataTransfer xfer = new DataTransfer(srcTable, destTable, linkages);
            string err = xfer.Transfer();

            if (!string.IsNullOrWhiteSpace(err))
            {
                MessageBox.Show(err, "Unable to Complete Transfer");
                return;
            }

        }

        private void saveBtn_Click(object sender, EventArgs e)
        {
            DialogResult result = MessageBox.Show("Save Configurations For Future Use?", "", MessageBoxButtons.YesNo);
            if (result != DialogResult.Yes) return;

            string fileName = "";
            UserInput input = new UserInput("Please Enter File Name");
            input.OnOkButtonClick += (obj, evt) =>
            {
                fileName = input.InputValue;

                BindingSource bs = (BindingSource)linkageBox.DataSource;

                List<ColumnLinkage> linkages = new List<ColumnLinkage>();

                ColumnLinkage[] linkagesArr = new ColumnLinkage[bs.Count];

                bs.CopyTo(linkagesArr, 0);

                linkages.AddRange(linkagesArr);

                DatabaseTransferSerializer dtf = new DatabaseTransferSerializer()
                {
                    LinkageList = linkages,
                    SourceTable = this.srcTable,
                    DestinationTable = this.destTable,
                    SourceConnector = this.srcTable.Database.Connector,
                    DestinationConnector = this.destTable.Database.Connector
                };

                bool success = DatabaseTransferSerializer.Serialize(dtf, fileName);

            };
            input.ShowDialog();

        }

        private void closeBtn_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}
